﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Windows.Forms.DataVisualization.Charting;
using System.IO.Ports;
using System.IO;

namespace Hi5
{
    public partial class Form1 : Form
    {
        Series series1 = new Series("Spline");

        private bool serialListening = false; //表示正在接收处理数据（在DataReceived事件中）
        private bool serialClosing = false;  //表示串口是否处于关闭状态，关闭时不要再接收数据
        static int displayWindow = 0;  //有三个显示窗口可切换
        private bool KeyShift, keyW, keyS, keyA, keyD, keyUp, keyDown, keyLeft, keyRight;  //shift+按键才有用
        private int progressBarValue = 0;  //电流bar
        private bool recordEnabled = false;
        private bool firstCreateFile = true;  //打开还是新建文件

        private string settingfileName = "";  //默认的设置
        private string recordFileName = "";

        private List<byte> buffer = new List<byte>(4096);  //用来保存接收到的数据
        private List<byte> frameBuf = new List<byte>(100);  //用来保存接收到的数据

        private int receivedDataLength = 0;

        private float pointY;

        private int rxNum = 0;  //串口接收数据的个数
        private int txNum = 0;  //串口发送数据的个数

        const int SHOWNUM = 50;   //波形图中显示数据的个数

        System.Diagnostics.Stopwatch watch = new System.Diagnostics.Stopwatch();
        bool firstRUN = true;

        public Form1()
        {
            InitializeComponent();
            System.Windows.Forms.Control.CheckForIllegalCrossThreadCalls = false;
            this.KeyPreview = true;

        }


        bool isComplete()
        {
            int i;
            int frameLength;
            for (i = 0; i < buffer.Count-1; i++)
            {
                if (buffer[i] == 0xff && buffer[i + 1] == 0xff && (i + 2) < buffer.Count)  //帧头
                {
                    frameLength = buffer[i + 2];
                    if ((i + 2 + frameLength + 1) < buffer.Count)
                    {
                        if (buffer[i + 2 + frameLength] == 0x0d && buffer[i + 2 + frameLength + 1] == 0x0a)  //帧尾
                        {
                            frameBuf.Clear();
                            for (int j = 0; j < (frameLength - 1); j++)
                            {
                                
                                frameBuf.Add(buffer[i + 3 + j]);
                            }
                            buffer.RemoveRange(0, i + frameLength + 4);

                            return true;
                        }
                    }
                }
            }
            return false;
        }

        void serial_DataReceived(object sender, SerialDataReceivedEventArgs e)
        {

            if (!firstRUN)
            {
                watch.Stop();

                TimeSpan timespan = watch.Elapsed;

                watch.Reset();
            }

            firstRUN = false;
            watch.Start();

            serialListening = true;

            int high, low;  

            if (receivedDataLength >= 3000) //不让series里边数据太多
            {
                receivedDataLength = 0;
                series1.Points.Clear();
            }

            if (recordEnabled)  //如果开启了数据记录
            {
                FileStream fs;
                if (firstCreateFile)
                {
                    fs = new FileStream(recordFileName, FileMode.Create);
                    firstCreateFile = false;
                }
                else
                    fs = new FileStream(recordFileName, FileMode.Open);

                StreamWriter sw = new StreamWriter(fs);

                if (!serialClosing)
                {
                    try
                    {
                        int cnt = serialPort1.BytesToRead;
                        string printStr = "";

                        byte[] buf = new byte[cnt];
                        serialPort1.Read(buf, 0, cnt);
                        rxNum += cnt;
                        textBox2.Text = rxNum.ToString();

                        for (int i = 0; i < buf.Length; i++)
                        {
                            string str = Convert.ToString(buf[i], 16).ToUpper();  
                            buffer.Add(buf[i]);  // 把数据取出来放到全局buffer中

                            if(str.Length == 1)
                                str = "0x0" + str + " ";
                            else
                                str = "0x" + str + " ";
                            
                            printStr = printStr + str;

                                                       
                        }
                        textBox14.AppendText(printStr);

                        while (isComplete())
                        {
                            printStr = "";

                            if (cnt > 500)
                            {
                                series1.Points.Clear();
                            }
                            else
                            {
                                /*  画图  */
                                high = frameBuf[0];
                                low = frameBuf[1];
                                pointY = ((float)(high * 256 + low)) / 100;
                                receivedDataLength ++;

                                series1.Points.AddY(pointY);

                                chart1.ChartAreas[0].AxisX.ScaleView.Position = series1.Points.Count - SHOWNUM;

                                chart1.ChartAreas[0].AxisY.Minimum = (int)pointY - 2;
                                chart1.ChartAreas[0].AxisY.Maximum = (int)pointY + 5;
                            }
                            


                            for (int i = 0; i < frameBuf.Count; i++)
                            {
                                string str = Convert.ToString(frameBuf[i], 16).ToUpper();

                                if (str.Length == 1)
                                    str = "0" + str + " ";
                                else
                                    str = str + " ";

                                printStr = printStr + str;
                               

                            }

                            fs.Seek(0, SeekOrigin.End);
                            sw.Write(printStr);
                            sw.Write("\n");
                        }
                    }
                    finally{}
                }
                sw.Close();
                fs.Close();
            }
            else  //如果没有开启数据记录
            {
                if (!serialClosing)
                {
                    if (!checkBox2.Checked) //如果是字符显示
                    {
                        string str = serialPort1.ReadExisting();//字符串方式读
                        textBox14.AppendText(str);//添加内容
                    }
                    else
                    {
                        int cnt = serialPort1.BytesToRead;
                        string printStr = "";

                        byte[] buf = new byte[cnt];
                        serialPort1.Read(buf, 0, cnt);
                        rxNum += cnt;
                        textBox2.Text = rxNum.ToString();

                        /* 调试显示 */
                        textBox6.Text = Convert.ToString(cnt);
                        textBox7.Text = Convert.ToString(buffer.Count);
                       
                        for (int i = 0; i < buf.Length; i++)
                        {
                            buffer.Add(buf[i]);  //把数据取出来放到全局buffer中

                            string str = Convert.ToString(buf[i], 16).ToUpper();
                            
                            if (str.Length == 1)
                                str = "0x0" + str + " ";
                            else
                                str = "0x" + str + " ";
                            
                            printStr = printStr + str;   

                            
                        }
                        textBox14.AppendText(printStr);
                        

                        while (isComplete())  //每次得到一个完整的帧，直到buffer中没有完整的帧
                        {
                            if (cnt > 500)
                            {
                                series1.Points.Clear();
                            }
                            else
                            {
                                //  画图  
                                high = frameBuf[0];
                                low = frameBuf[1];
                                pointY = ((float)(high * 256 + low)) / 100;
                                receivedDataLength++;

                                lock(chart1)
                                {
                                    series1.Points.AddY(pointY);
                                    if (series1.Points.Count >= SHOWNUM)
                                    {
                                        chart1.ChartAreas[0].AxisX.ScaleView.Position = series1.Points.Count - SHOWNUM;
                                        chart1.ChartAreas[0].AxisX.ScaleView.Size = SHOWNUM;
                                    }
                                        
                                    chart1.ChartAreas[0].AxisY.Minimum = (int)pointY - 2;
                                    chart1.ChartAreas[0].AxisY.Maximum = (int)pointY + 5;
                                }
                            }
                        } 
                    }
                }  
            }

            serialListening = false;
        }


        private void Form1_Load(object sender, EventArgs e)
        {
            /* chart初始化  */
            chart1.Series.Clear();
            series1.ChartType = SeriesChartType.Spline;
            chart1.Series.Add(series1);

            chart1.Visible = false;
            pictureBox1.Visible = false;

            /* 串口初始化  */
            serialPort1.BaudRate = 115200;
            serialPort1.DataBits = 8;
            serialPort1.Parity = Parity.None;
            serialPort1.StopBits = StopBits.One;

            serialPort1.DataReceived += serial_DataReceived; //注册串口接收事件
            serialPort1.Encoding = Encoding.GetEncoding("GB2312");

            string[] ports = SerialPort.GetPortNames();

            if (ports.GetLength(0) != 0)
            {
                foreach (string port in ports)
                {
                    comboBox1.Items.Add(port);
                }
                comboBox1.SelectedIndex = 0;  //默认选择第一个可用串口
            }
            comboBox2.SelectedIndex = 7;  //选择默认波特率为115200

            settingfileName = System.Environment.CurrentDirectory + "\\setting.txt";

            if (File.Exists(settingfileName))
            {
                string line = "";
                System.IO.StreamReader sr = new System.IO.StreamReader(settingfileName);
                if ((line = sr.ReadLine()) != null)
                {
                    sr.Close();
                    recordFileName = line;
                }
                else
                {
                    sr.Close();
                    recordFileName = System.Environment.CurrentDirectory + "\\recordData.txt";
                    System.IO.StreamWriter sw = new System.IO.StreamWriter(settingfileName);
                    sw.WriteLine(recordFileName);
                    sw.Close();
                }
            }
            else
            {
                FileStream fs = new FileStream(settingfileName, FileMode.Create);
                System.IO.StreamWriter sw = new System.IO.StreamWriter(fs);
                recordFileName = System.Environment.CurrentDirectory + "\\recordData.txt";
                sw.WriteLine(recordFileName);
                sw.Close();
                fs.Close();
            }

        }

        private void Form1_FormClosed(object sender, FormClosedEventArgs e)
        {
            if (serialPort1.IsOpen)
            {
                serialClosing = true;
                while (serialListening)
                {
                    Application.DoEvents();
                }
                serialPort1.Close();
                serialClosing = false;
            }
        }


        private void button2_Click(object sender, EventArgs e)
        {
            if (saveFileDialog1.ShowDialog() == DialogResult.OK)
            {
                recordFileName = saveFileDialog1.FileName + ".txt";
                FileStream fs = new FileStream(settingfileName, FileMode.Create);
                StreamWriter sw = new StreamWriter(fs);
                sw.WriteLine(recordFileName);
                sw.Close();
                fs.Close();
            }
        }

        private void button1_Click(object sender, EventArgs e)
        {
            if (serialPort1.IsOpen)
            {
                button3.Text = "Save";  //先把保存关了
                recordEnabled = false;
                button3.Enabled = false;

                serialClosing = true;
                

                while (serialListening)
                {
                    Application.DoEvents();
                }

                serialPort1.Close();
                
                button1.Text = "Open";
                serialClosing = false;
 
                button1.BackColor = System.Drawing.Color.Green;
                
            }
            else 
            {
                try
                {
                    serialPort1.PortName = comboBox1.Text;
                    serialPort1.BaudRate = Convert.ToInt32(comboBox2.Text, 10);//十进制数据转换
                    serialPort1.Open();
                    button1.Text = "Close";
                    button1.BackColor = System.Drawing.Color.Red;
                    button3.Enabled = true;
                }
                catch
                {
                    MessageBox.Show("端口错误,请检查串口", "错误");
                    button1.Text = "Open";
                }
            }

        }

        private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (serialPort1.IsOpen)
            {
                serialClosing = true;
                while (serialListening)  //切换之前，先把串口接收数据接完。 
                {
                    Application.DoEvents();
                }
                serialPort1.Close();
                serialClosing = false;
                serialPort1.PortName = comboBox1.Text;
                try
                {
                    serialPort1.Open();
                }
                catch
                {
                    MessageBox.Show("端口错误,请检查串口", "错误");
                    button1.Text = "Open";
                    button1.BackColor = System.Drawing.Color.Green;
                }
                
            }
            else 
            {
                serialPort1.PortName = comboBox1.Text;
            }
        }

        private void comboBox2_SelectedIndexChanged(object sender, EventArgs e)
        {
            try
            {
                serialPort1.BaudRate = Convert.ToInt32(comboBox2.Text, 10);//十进制数据转换 
            }
            catch
            {
                MessageBox.Show("修改波特率错误，请先关闭串口再修改", "错误");
            }
        }

 
        private void button23_Click(object sender, EventArgs e)
        {
            byte[] Data = new byte[1];
            if (serialPort1.IsOpen)
            {
                if (textBox1.Text != "")
                {
                    if (!checkBox1.Checked)  //如果发送模式是字符模式
                    {
                        try
                        {
                            serialPort1.WriteLine(textBox1.Text);
                        }
                        catch
                        {                           
                            serialClosing = true;
                            while (serialListening)
                            {
                                Application.DoEvents();
                            }
                            serialPort1.Close();
                            serialClosing = false;
                            button1.Text = "Open";
                            button1.BackColor = System.Drawing.Color.Green;
                            MessageBox.Show("串口数据写入错误", "错误");//出错提示
                        }
                    }
                    else  
                    { 
                        for (int i = 0; i < (textBox1.Text.Length + 1) / 3; i++) //两个字节之间用空格隔开
                        {
                            try
                            {
                                Data[0] = Convert.ToByte(textBox1.Text.Substring(i * 3, 2), 16);
                                serialPort1.Write(Data, 0, 1);//循环发送（如果输入字符为0A0BB,则只发送0A,0B）
                            }
                            catch 
                            {
                                MessageBox.Show("注意十六进制格式是否正确,两个字节之间用空格隔开", "错误");//出错提示
                                return;
                            }
  
                        }
                    }
                }
            }
            else
            {
                MessageBox.Show("打开串口", "警告");
            }
        }



        private void button15_Click(object sender, EventArgs e)
        {
            if (displayWindow != 0)
            {
                displayWindow = 0;
                button15.BackgroundImage = Properties.Resources.serialbuttton_on;
                button16.BackgroundImage = Properties.Resources.strain;
                button17.BackgroundImage = Properties.Resources.motor;
                textBox14.Visible = true;
                checkBox2.Enabled = true;
                chart1.Visible = false;
            }
        }

        private void button16_Click(object sender, EventArgs e)
        {
            if (displayWindow != 1)
            {
                displayWindow = 1;
                button15.BackgroundImage = Properties.Resources.serialbuttton;
                button16.BackgroundImage = Properties.Resources.strain_on;
                button17.BackgroundImage = Properties.Resources.motor;
                textBox14.Visible = false;
                checkBox2.Enabled = false;
                chart1.Visible = true;
            }
        }
        private void button17_Click(object sender, EventArgs e)
        {
            if (displayWindow != 2)
            {
                displayWindow = 2;
                button15.BackgroundImage = Properties.Resources.serialbuttton;
                button16.BackgroundImage = Properties.Resources.strain;
                button17.BackgroundImage = Properties.Resources.motor_on;
                textBox14.Visible = false;
                checkBox2.Enabled = false;
                chart1.Visible = true;
            }
        }

        private void Form1_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.Shift)  //shift功能键按下
                KeyShift = true;  //标志位置位
            switch (e.KeyCode)  //功能标志置位
            {
                case Keys.W:
                    keyW = true;
                    button11.BackgroundImage = Properties.Resources.buttonUp;
                    System.Media.SystemSounds.Beep.Play();
                    break;
                case Keys.S:
                    keyS = true;
                    button10.BackgroundImage = Properties.Resources.buttonUp;
                    System.Media.SystemSounds.Beep.Play();                  
                    break;
                case Keys.A:
                    keyA = true;
                    button9.BackgroundImage = Properties.Resources.buttonUp;
                    System.Media.SystemSounds.Beep.Play(); 
                    break;
                case Keys.D:
                    keyD = true;
                    button8.BackgroundImage = Properties.Resources.buttonUp;
                    System.Media.SystemSounds.Beep.Play();
                    break;
                case Keys.Up:
                    keyUp = true;
                    button4.BackgroundImage = Properties.Resources.buttonUp;
                    System.Media.SystemSounds.Hand.Play();
                    break;
                case Keys.Down:
                    keyDown = true;
                    button5.BackgroundImage = Properties.Resources.buttonUp;
                    System.Media.SystemSounds.Hand.Play();
                    break;
                case Keys.Left:
                    keyLeft = true;
                    button6.BackgroundImage = Properties.Resources.buttonUp;
                    System.Media.SystemSounds.Hand.Play();
                    if (progressBarValue > 0)
                    {
                        progressBar1.Value = --progressBarValue;
                    }
                    if (progressBarValue <= 100)
                        progressBar1.ForeColor = Color.Red;
                    if (progressBarValue <= 75)
                        progressBar1.ForeColor = Color.Yellow;
                    if (progressBarValue <= 50)
                        progressBar1.ForeColor = Color.Lime;
                    textBox13.Text = Convert.ToString(progressBarValue);
                    break;
                case Keys.Right:
                    keyRight = true;
                    button7.BackgroundImage = Properties.Resources.buttonUp;
                    System.Media.SystemSounds.Hand.Play();
                    if (progressBarValue < 100)
                    {
                        progressBar1.Value = ++progressBarValue;
                    }
                    if(progressBarValue >= 0)
                        progressBar1.ForeColor = Color.Lime;
                    if (progressBarValue > 50)
                        progressBar1.ForeColor = Color.Yellow;
                    if (progressBarValue > 75)
                        progressBar1.ForeColor = Color.Red;
                    textBox13.Text = Convert.ToString(progressBarValue);

                    break;
                default:
                    break;
            }
        }

        private void Form1_KeyUp(object sender, KeyEventArgs e)
        {
            if (KeyShift)
            {
                if (keyW)
                {
                    keyW = false;  
                }
                else if (keyS)
                {
                    keyS = false;    
                }
                else if (keyA)
                {
                    keyA = false;    
                }
                else if (keyD)
                {
                    keyD = false;  
                }
                else if (keyUp)
                {
                    keyUp = false;
                }
                else if (keyDown)
                {
                    keyDown = false;                  
                }
                else if (keyLeft)
                {
                    keyLeft = false;
                }
                else if (keyRight)
                {
                    keyRight = false;
                }
            }
            else 
            { 
                keyW = false;
                keyS = false;
                keyA = false; 
                keyD = false; 
                keyUp = false;
                keyDown = false; 
                keyLeft = false; 
                keyRight = false;
            }
            button4.BackgroundImage = Properties.Resources._3;
            button5.BackgroundImage = Properties.Resources._3;
            button6.BackgroundImage = Properties.Resources._3;
            button7.BackgroundImage = Properties.Resources._3;
            button8.BackgroundImage = Properties.Resources._3;
            button9.BackgroundImage = Properties.Resources._3;
            button10.BackgroundImage = Properties.Resources._3;
            button11.BackgroundImage = Properties.Resources._3;
            KeyShift = false;
        }

        private void button3_Click(object sender, EventArgs e)
        {
            if (button3.Text == "Save")
            {
                button3.Text = "Stop";
                recordEnabled = true;
            }
            else
            {
                button3.Text = "Save";
                recordEnabled = false;
            }
        }


        private void button12_Click(object sender, EventArgs e)
        {
            byte[] Data = new byte[1];
            int j;
            if (serialPort1.IsOpen)
            {
                if (textBox4.Text != "")
                {
                    if (Int32.TryParse(textBox4.Text, out j))
                    {
                        Data[0] = (Byte)(j / 256);
                        serialPort1.Write(Data, 0, 1);
                        Data[0] = (Byte)(j % 256);
                        serialPort1.Write(Data, 0, 1);
                    }
                    else
                        MessageBox.Show("String could not be parsed.", "警告");

                    if (textBox5.Text == "")
                        j = 0;
                    else
                    {
                        Int32.TryParse(textBox5.Text, out j);
                        Data[0] = (Byte)(j / 256);
                        serialPort1.Write(Data, 0, 1);
                        Data[0] = (Byte)(j % 256);
                        serialPort1.Write(Data, 0, 1);
                    }

                    Data[0] = 0x00;     /* 帧尾前的最后一个字节表示是哪个数据帧，0x00表示力矩参数 */
                    serialPort1.Write(Data, 0, 1);
                    Data[0] = 0x0d;     /* 帧尾0x0d 0x0a */
                    serialPort1.Write(Data, 0, 1);
                    Data[0] = 0x0a;
                    serialPort1.Write(Data, 0, 1);
                }

            }
            else
            {
                MessageBox.Show("打开串口", "警告");
            }

        }

        private void button13_Click(object sender, EventArgs e)
        {
            byte[] Data = new byte[1];
            int j;
            if (serialPort1.IsOpen)
            {
                if (textBox9.Text != "")
                {
                    if (Int32.TryParse(textBox9.Text, out j))
                    {
                        Data[0] = (Byte)(j / 256);
                        serialPort1.Write(Data, 0, 1);
                        Data[0] = (Byte)(j % 256);
                        serialPort1.Write(Data, 0, 1);
                    }
                    else
                        MessageBox.Show("String could not be parsed.", "警告");

                    if (textBox8.Text == "")
                        j = 0;
                    else
                    {
                        Int32.TryParse(textBox8.Text, out j);
                        Data[0] = (Byte)(j / 256);
                        serialPort1.Write(Data, 0, 1);
                        Data[0] = (Byte)(j % 256);
                        serialPort1.Write(Data, 0, 1);
                    }

                    Data[0] = 0x01;     /* 帧尾前的最后一个字节表示是哪个数据帧，0x01表示速度参数 */
                    serialPort1.Write(Data, 0, 1);
                    Data[0] = 0x0d;     /* 帧尾0x0d 0x0a */
                    serialPort1.Write(Data, 0, 1);
                    Data[0] = 0x0a;
                    serialPort1.Write(Data, 0, 1);
                }

            }
            else
            {
                MessageBox.Show("打开串口", "警告");
            }
        }

        private void button14_Click(object sender, EventArgs e)
        {
            byte[] Data = new byte[1];
            int j;
            if (serialPort1.IsOpen)
            {
                if (textBox12.Text != "")
                {
                    if (Int32.TryParse(textBox12.Text, out j))
                    {
                        Data[0] = (Byte)(j / 256);
                        serialPort1.Write(Data, 0, 1);
                        Data[0] = (Byte)(j % 256);
                        serialPort1.Write(Data, 0, 1);
                    }
                    else
                        MessageBox.Show("String could not be parsed.", "警告");

                    if (textBox11.Text == "")
                        j = 0;
                    else
                    {
                        Int32.TryParse(textBox11.Text, out j);
                        Data[0] = (Byte)(j / 256);
                        serialPort1.Write(Data, 0, 1);
                        Data[0] = (Byte)(j % 256);
                        serialPort1.Write(Data, 0, 1);
                    }

                    Data[0] = 0x02;     /* 帧尾前的最后一个字节表示是哪个数据帧，0x02表示位置参数 */
                    serialPort1.Write(Data, 0, 1);
                    Data[0] = 0x0d;     /* 帧尾0x0d 0x0a */
                    serialPort1.Write(Data, 0, 1);
                    Data[0] = 0x0a;
                    serialPort1.Write(Data, 0, 1);
                }

            }
            else
            {
                MessageBox.Show("打开串口", "警告");
            }
        }

        private void button18_Click(object sender, EventArgs e)
        {
            textBox2.Text = "0";
            textBox3.Text = "0";
            textBox14.Text = "0";
            rxNum = 0;
            receivedDataLength = 0;
            series1.Points.Clear();

        }




    }
}
